import json
from datetime import datetime

from sqlalchemy.ext.asyncio import AsyncSession

from module_admin.entity.vo.common_vo import CrudResponseModel
from module_stock.dao.info_dao import InfoDao
from module_stock.entity.vo.info_vo import InfoModel, InfoPageQueryModel
from module_xtquant import get_all_stock_list, get_stock_data
from utils.string_util import StringUtil
from utils.time_format_util import TimeFormatUtil


class InfoService:
    """
    股票基础信息模块服务层
    """

    @classmethod
    async def get_info_list_services(
            cls, query_db: AsyncSession, query_object: InfoPageQueryModel, is_page: bool = False
    ):
        """
        获取股票基础信息列表信息service

        :param query_db: orm对象
        :param query_object: 查询参数对象
        :param is_page: 是否开启分页
        :return: 股票基础信息列表信息对象
        """
        info_list_result = await InfoDao.get_info_list(query_db, query_object, is_page)

        return info_list_result

    @classmethod
    async def check_stock_exists_services(cls, query_db: AsyncSession, stock_code: str):
        """
        检查股票代码是否存在service

        :param query_db: orm对象
        :param stock_code: 股票代码
        :return: 股票是否存在结果
        """
        stock_info = await InfoDao.get_info_detail_by_id(query_db, stock_code)

        return stock_info is not None

    @classmethod
    async def sync_full_stock_info_services(cls, query_db: AsyncSession):
        """
        全量更新或添加股票信息到数据库service

        :param query_db: orm对象
        :return: 同步结果
        """

        # 第一步：获取所有股票代码
        stock_list = list(set(get_all_stock_list()))
        # 统计信息
        added_count = 0
        updated_count = 0
        unchanged_count = 0
        # 第二步和第三步：遍历股票代码，获取股票信息并插入数据库
        for stock_code in stock_list:

            info_model = await InfoService.create_info_model(stock_code)

            # 检查数据库中是否已存在该股票代码的记录
            existing_info = await InfoDao.get_info_detail_by_id(query_db, stock_code=stock_code)

            if existing_info:
                # 如果现有记录的MD5与当前MD5一致，则跳过更新
                if existing_info.interface_data_md5 == info_model.stock_data_md5:
                    unchanged_count += 1
                    continue

                # 更新现有记录
                await InfoDao.edit_info_dao(query_db, info_model.model_dump(exclude_unset=True))
                updated_count += 1
            else:
                # 添加新记录
                await InfoDao.add_info_dao(query_db, info_model)
                added_count += 1

        # 提交事务
        await query_db.commit()

        return CrudResponseModel(
            is_success=True,
            message=f"同步完成，新增{added_count}条记录，更新{updated_count}条记录，{unchanged_count}条记录无变化"
        )

    @classmethod
    async def create_info_model(cls, stock_code) -> InfoModel:
        # 获取股票基础信息
        stock_data = get_stock_data(stock_code)
        # 将数据转换为JSON字符串
        stock_data_json = json.dumps(stock_data, ensure_ascii=False) if stock_data else None
        stock_data_md5 = StringUtil.get_md5(stock_data_json) if stock_data_json else None
        return InfoModel(
            stockCode=stock_code,
            stockName=stock_data.get('InstrumentName'),
            exchangeId=stock_data.get('ExchangeID'),
            instrumentStatus=str(stock_data.get('InstrumentStatus')),
            ipoDate=TimeFormatUtil.parse_date_string(stock_data.get('OpenDate')),
            expireDate=TimeFormatUtil.parse_date_string(stock_data.get('ExpireDate')),
            interfaceData=stock_data_json,
            interfaceDataMd5=stock_data_md5,
            updateTime=datetime.now(),
            createTime=datetime.now()
        )

    @classmethod
    async def sync_incremental_stock_info_services(cls, query_db: AsyncSession):
        """
        增量更新股票信息到数据库service

        :param query_db: orm对象
        :return: 同步结果
        """
        from module_xtquant import get_all_stock_list

        # 第一步：获取所有股票代码
        stock_list = list(set(get_all_stock_list()))

        # 第二步：一次性获取数据库中所有股票代码
        existing_stocks = await InfoDao.get_all_stock_codes(query_db)
        existing_stock_codes = set([stock.stock_code for stock in existing_stocks])

        # 统计信息
        added_count = 0

        # 第三步：找出新增的股票代码
        new_stock_codes = [code for code in stock_list if code not in existing_stock_codes]

        # 第四步：批量处理新增的股票
        for stock_code in new_stock_codes:
            # 构造InfoModel对象
            info_model = await InfoService.create_info_model(stock_code)
            # 添加新记录
            await InfoDao.add_info_dao(query_db, info_model)
            added_count += 1

        # 提交事务
        await query_db.commit()

        return CrudResponseModel(
            is_success=True,
            message=f"增量同步完成，新增{added_count}条记录"
        )
